import java.awt.*;
import java.awt.font.TextAttribute;
import javax.swing.*;
import java.util.HashMap;

/**
 * A prototype class to experiment with how rendered text will be written to the display.
 * 
 * @author Joe Thomas
 * @version 0.2
 */
public class Display 
{
    private static final int WINDOW_WIDTH = 720;
    private static final int WINDOW_HEIGHT = 220;
    private static final Color FOREGROUND_COLOR = Color.BLACK;
    private static final String DEFAULT_FONT = "Ariel";
    private static final float TEXT_SIZE = 14;
    
    // instance variables (fields). 
    private JFrame window;
    private JPanel container;
    private State state;

    /**
     * A Constructor to initialise the instance variables of a new Display.
     */
    public Display()
    {
        state = new State();
        window = new JFrame("Render Output Prototype");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
        container = (JPanel) window.getContentPane();
        container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
        container.setBackground(Color.WHITE);
        window.setVisible(true);
    }

    /**
     * The primary method of the class. It takes a String of text (the next part of text to be rendered, aquires the various formatting states from the State class and writes
     * the text to this display with these states.
     * @param text the text to be formatted to the display.
     */
    public void addText(String text)
    {
       // this first section is used to compose a HashMap of all the formatting attributes the text font should have/

        HashMap map = new HashMap();
        map.put(TextAttribute.FOREGROUND, FOREGROUND_COLOR);
        map.put(TextAttribute.FAMILY, DEFAULT_FONT);
        map.put(TextAttribute.SIZE, TEXT_SIZE);

        if (state.getState(State.BOLD)) {
            map.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);  // add the bold attribute.
        }
        if (state.getState(State.ITALIC)) {
            map.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);  // add the italic attribute.
        }
        if (state.getState(State.UNDERLINED)) {
            map.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);  // add the underlined attribute.
        }
        
        Font f = new Font(map); // create a new font the text will have by using the map of text attributes.
        boolean wrap = state.getState(State.WRAPPED); // get the wrapping policy.

        String indentation = ""; // get the indentation value.
        for (int i = 0 ; i < state.getIndentation() ; i++) {
            indentation += " ";
        }
        
        String heading = ""; // get the heading value.
        if (state.getHeading() != 0.0) {
            heading += state.getHeading() + ": ";
        }
        
        // if the text does not need to be wrapped, place the text into a JLabel.
        if (!state.getState(State.WRAPPED)) {
            JLabel label = new JLabel(indentation + heading + text);
            label.setFont(f);
            container.add(label); // add the label to the GUI.
        }
        // otherwise if the text does not need to be wrapped, place the text into a JTextPane which wraps text by default.
        else { 
            JTextPane pane = new JTextPane();
            pane.setEditable(false); // make the text within the text pane uneditable.
            pane.setText(indentation + heading + text); // add the text to the text pane.
            pane.setFont(f); // set the font.
            container.add(pane); // add the pane to the GUI.
        }
    }
    
    /**
     * A method to write an image to the display using a pathname to create an ImageIcon which is inside a JLabel.
     * @param filePath the file path of the image to be displayed
     */
    public void addImage(String filePath)
     {
        JLabel image = new JLabel();
        image.setIcon(new ImageIcon(filePath));
        container.add(image);
    }
    
    /**
     * A method to return the state variable should external classes need to reference it.
     * @return the current state.
     */
    public State getState()
    {
        return state;
    }
    
}